//
// Created by YE on 2024/1/7.
//

#ifndef YCH_INTERPRETER_PARSER_H
#define YCH_INTERPRETER_PARSER_H

#include "lexer.h"
#include "../common/ych_object.h"
#include "symbols.h"

typedef YCH_STATE Parser_State;
typedef YCH_STATE Syn_State;
typedef YCH_STATE Sem_State;
#define PARSER_END 2
#define PARSER_ERROR 1
#define PARSER_OK 0


#define SYN_ERROR 1
#define SYN_OK 0

typedef unsigned int T;

#define FIRST_NT (LAST_TK_+1)
enum NT_ {
    NT_S = FIRST_NT,

    NT_DS, NT_DTYPE, NT_DL, NT_DV, NT_DA, NT_DF,

    NT_MAT_V, NT_MAT_V_IN, NT_MAT_V_IN_IN, NT_MAT_V_1_LIST, NT_MAT_V_2_LIST,

    NT_FS, NT_FS_PARAM_LIST, NT_FS_R, NT_FS_PARAM_LIST_F, NT_S_LIST,

    NT_RS, NT_R_F,

    NT_ES, NT_E1, NT_E2, NT_E3, NT_E4, NT_E5, NT_E6, NT_E7, NT_E8, NT_E9, NT_E10,
    NT_F, NT_F_F, NT_F_CONST, NT_F_F_F, NT_F_PARAM_LIST, NT_F_PARAM_LIST_F,

    NT_E1_F, NT_E3_F, NT_E4_F, NT_E5_F, NT_E6_F, NT_E8_F, NT_E9_F, NT_E10_F,

    NT_IS, NT_IS_ELSE,

    NT_WS,

    NT_BS,

    NT_CS,

    NT_DELS, NT_DELS_F,

    LAST_NT_
};
#define FIRST_ACTION (LAST_NT_+1)
enum AC_ {
    AC_PUSH_CONST = FIRST_ACTION,
    AC_MALLOC_VAR,
    AC_ASSIGN_FIRST,
    AC_SET_EKIND,
    AC_SEM_POP, AC_POP,
    AC_SEM_PUSH_VAR,
    AC_SEM_PUSH_FUNC,
    AC_ADD, AC_SUB,
    AC_MUL, AC_DIV, AC_INNER, AC_MOD,
    AC_NEG,
    AC_POW,
    AC_LESS, AC_GREATER, AC_LESSEQUAL, AC_GREATEREQUAL, AC_EQUAL, AC_NOTEQUAL,
    AC_OR, AC_AND, AC_NOT,
    AC_SEM_ASSIGN_END, AC_PUSH_ASSIGN,
    AC_IF_JUDGE, AC_WHILE_JUDGE,
    AC_PUSH_WHILE, AC_WHILE_END, AC_BREAK,
    AC_IF_END, AC_PUSH_ELSE, AC_ELSE_END,
    AC_FUNC_END, AC_FUNC_COUNT_PARAM,
    AC_DEF_FUNC_START, AC_DEF_COUNT_PARAMS, AC_RETURN, AC_DEF_FUNC_END,
    AC_MAT_COUNT_ROW,AC_MAT_COUNT_COL,AC_MAT_END,AC_MAT_START,
    AC_INDEX,
};
enum E_KIND {
    ENONE, EINT, EFLOAT, EMAT, EBOOL,ESTRING
};
typedef struct WhileEvn {
    WhileEvn *pre;
} WhileEvn;
typedef struct FuncState {
    FuncState *pre;
    unsigned int count;
    unsigned int params;
    unsigned int fp;
    unsigned int t_var_nums;
} FuncState;
struct MatState{
    unsigned int row,col;
    unsigned int t_col;
    unsigned int mat_malloc_p;
};
struct CState {
    E_KIND ekind;
    unsigned int vm_mem_p;
    unsigned int vm_i_p;
    unsigned int vm_i_f_p;
    unsigned int vm_int_const_p;
    unsigned int vm_float_const_p;
    unsigned int vm_string_const_p;
    unsigned int vm_c_func_p;
    unsigned int func_mem_p;
    bool declare_func;
    WhileEvn *whileEvn;
    FuncState *funcState;
    FuncInfo *funcInfo;
    MatState matState;
};
enum Mt {
    MT_NONE,
    MT_VAR,
    MT_T,
    MT_INT_VAR,
    MT_FLOAT_VAR,
    MT_MAT_VAR,
    MT_BOOL_VAR,
    MT_STRING_VAR,
    MT_INT_CONST,
    MT_FLOAT_CONST,
    MT_BOOL_CONST,
    MT_STRING_CONST,
    MT_ASSIGN,
    MT_IP,
    MT_WP
};
struct MInfo {
    Mt mt;
    union V {
        unsigned int p;    //
        Int i;
        Float f;
        bool b;
    } v;
};
typedef std::vector<MInfo> Sen_Stack;

static Syn_State deduce(T x, T w, std::stack<T> *stack);

static void pushR(const T *production, int s, std::stack<T> *stack);

class Parser {
public:
    explicit Parser(Lexer *lexer);

    ~Parser();

    Parser_State parse();

    Lexer *lexer;
    Token current_token;
    std::stack<T> syn;
    CState cs;
    Sen_Stack sem;
    Sen_Stack if_sem;

    void load_CLib();

    String error_string(State st) const;
};


#endif //YCH_INTERPRETER_PARSER_H
